package org.com.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import org.com.common.AliPayConfig;
import org.com.common.R;
import org.com.pojo.UserBalance;
import org.com.pojo.Transactions;
import org.com.service.UserBalanceService;
import org.com.service.TransactionsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/api/alipay")
public class AliPayController {
    // 支付宝沙箱网关地址
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    private static final String FORMAT = "JSON";
    private static final String CHARSET = "UTF-8";
    // 签名方式
    private static final String SIGN_TYPE = "RSA2";

    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private TransactionsService transactionsService;

    // 创建支付宝客户端
    private AlipayClient getAlipayClient() {
        return new DefaultAlipayClient(
            GATEWAY_URL,
            aliPayConfig.getAppId(),
            aliPayConfig.getAppPrivateKey(),
            FORMAT,
            CHARSET,
            aliPayConfig.getAlipayPublicKey(),
            SIGN_TYPE
        );
    }

    // 发起充值支付
    @PostMapping("/recharge")
    public R recharge(HttpServletRequest request, @RequestParam BigDecimal amount) {
        try {
            if (amount.compareTo(BigDecimal.ZERO) <= 0) {
                return R.error("充值金额必须大于0");
            }

            // 获取当前登录用户ID
            Integer userId = (Integer) request.getSession().getAttribute("userId");
            System.out.println("当前用户ID：" + userId);
            
            if (userId == null) {
                System.out.println("用户未登录！");
                return R.error("用户未登录");
            }

            // 生成订单号
            String outTradeNo = String.format("%d%d", userId, System.currentTimeMillis());
            System.out.println("生成订单号：" + outTradeNo);

            // 创建API对应的request
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(aliPayConfig.getReturnUrl());
            alipayRequest.setNotifyUrl(aliPayConfig.getNotifyUrl());

            // 填充业务参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", outTradeNo);
            bizContent.put("total_amount", amount.toString());
            bizContent.put("subject", "鼠鼠农业网-账户充值");
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");

            alipayRequest.setBizContent(bizContent.toString());
            System.out.println("支付请求参数：" + bizContent.toString());

            // 调用SDK生成表单
            AlipayTradePagePayResponse response = getAlipayClient().pageExecute(alipayRequest);
            if (response.isSuccess()) {
                System.out.println("创建支付订单成功，返回内容：" + response.getBody());
                return R.success("创建支付订单成功", response.getBody());
            } else {
                System.out.println("创建支付订单失败：" + response.getMsg());
                return R.error("创建支付订单失败：" + response.getMsg());
            }
        } catch (AlipayApiException e) {
            System.out.println("调用支付宝接口异常：" + e.getMessage());
            e.printStackTrace();
            return R.error("调用支付宝接口失败：" + e.getMessage());
        }
    }

    // 支付宝同步回调
    @GetMapping("/return")
    public String returnPage(HttpServletRequest request) {
        try {
            Map<String, String> params = convertRequestParams(request);
            System.out.println("收到支付宝同步回调参数：" + params);
            
            boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                aliPayConfig.getAlipayPublicKey(),
                CHARSET,
                SIGN_TYPE
            );

            if (signVerified) {
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                String totalAmount = params.get("total_amount");
                
                System.out.println("支付宝同步回调验签成功");
                System.out.println("订单号：" + outTradeNo);
                System.out.println("交易号：" + tradeNo);
                System.out.println("金额：" + totalAmount);
                
                // 构建前端跳转URL，带上支付参数
                String redirectUrl = String.format("%s/wallet?trade_no=%s&out_trade_no=%s&total_amount=%s&status=success",
                    aliPayConfig.getFrontendUrl(),
                    tradeNo,
                    outTradeNo,
                    totalAmount
                );
                
                // 使用window.opener来通知父窗口支付完成并关闭当前窗口
                return String.format(
                    "<script>" +
                    "if(window.opener) {" +
                    "    window.opener.postMessage({ type: 'payment_complete', success: true, data: { tradeNo: '%s', outTradeNo: '%s', totalAmount: '%s' } }, '%s');" +
                    "    window.close();" +
                    "} else {" +
                    "    window.location.href = '%s';" +
                    "}" +
                    "</script>",
                    tradeNo,
                    outTradeNo,
                    totalAmount,
                    aliPayConfig.getFrontendUrl(),
                    redirectUrl
                );
            } else {
                System.out.println("支付宝同步回调验签失败！");
                String redirectUrl = aliPayConfig.getFrontendUrl() + "/wallet?error=payment_verification_failed";
                return String.format(
                    "<script>" +
                    "if(window.opener) {" +
                    "    window.opener.postMessage({ type: 'payment_complete', success: false, error: 'payment_verification_failed' }, '%s');" +
                    "    window.close();" +
                    "} else {" +
                    "    window.location.href = '%s';" +
                    "}" +
                    "</script>",
                    aliPayConfig.getFrontendUrl(),
                    redirectUrl
                );
            }
        } catch (AlipayApiException e) {
            System.out.println("处理支付宝同步回调异常：" + e.getMessage());
            e.printStackTrace();
            String redirectUrl = aliPayConfig.getFrontendUrl() + "/wallet?error=payment_processing_error";
            return String.format(
                "<script>" +
                "if(window.opener) {" +
                "    window.opener.postMessage({ type: 'payment_complete', success: false, error: 'payment_processing_error' }, '%s');" +
                "    window.close();" +
                "} else {" +
                "    window.location.href = '%s';" +
                "}" +
                "</script>",
                aliPayConfig.getFrontendUrl(),
                redirectUrl
            );
        }
    }

    // 支付宝异步通知
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) {
        try {
            Map<String, String> params = convertRequestParams(request);
            System.out.println("收到支付宝异步通知参数：" + params);

            boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                aliPayConfig.getAlipayPublicKey(),
                CHARSET,
                SIGN_TYPE
            );

            if (signVerified) {
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                String tradeStatus = params.get("trade_status");
                String totalAmount = params.get("total_amount");

                System.out.println("支付宝异步通知验签成功");
                System.out.println("订单号：" + outTradeNo);
                System.out.println("交易号：" + tradeNo);
                System.out.println("交易状态：" + tradeStatus);
                System.out.println("交易金额：" + totalAmount);

                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    Integer userId = Integer.parseInt(outTradeNo.substring(0, outTradeNo.length() - 13));
                    BigDecimal amount = new BigDecimal(totalAmount);

                    System.out.println("开始处理充值");
                    System.out.println("用户ID：" + userId);
                    System.out.println("充值金额：" + amount);

                    try {
                        UserBalance userBalance = userBalanceService.getOne(
                            new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<UserBalance>()
                                .eq("user_id", userId)
                        );
                        
                        if (userBalance != null) {
                            System.out.println("当前用户余额：" + userBalance.getBalance());
                            
                            BigDecimal newBalance = userBalance.getBalance().add(amount);
                            Date now = new Date();
                            int updateResult = userBalanceService.updateBalance(
                                userBalance.getBalanceId(), 
                                newBalance,
                                now
                            );
                            
                            if (updateResult <= 0) {
                                System.out.println("更新用户余额失败！");
                                return "fail";
                            }
                            
                            System.out.println("更新后用户余额：" + newBalance);

                            // 记录交易
                            Transactions transaction = new Transactions();
                            transaction.setUserId(userId);
                            transaction.setBalanceId(userBalance.getBalanceId());
                            transaction.setDelta(amount);
                            transaction.setStatus(1);
                            transaction.setCreatedAt(now);
                            boolean saveResult = transactionsService.save(transaction);
                            
                            if (!saveResult) {
                                System.out.println("保存交易记录失败！");
                                return "fail";
                            }
                            
                            System.out.println("充值成功！");
                            return "success";
                        } else {
                            System.out.println("未找到用户余额信息！用户ID：" + userId);
                            return "fail";
                        }
                    } catch (Exception e) {
                        System.out.println("处理充值异常：" + e.getMessage());
                        e.printStackTrace();
                        return "fail";
                    }
                }
                return "success";
            } else {
                System.out.println("支付宝异步通知验签失败！");
                return "fail";
            }
        } catch (Exception e) {
            System.out.println("处理支付宝异步通知异常：" + e.getMessage());
            e.printStackTrace();
            return "fail";
        }
    }

    // 将request中的参数转换成Map
    private Map<String, String> convertRequestParams(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return params;
    }
}